/**
 * Program   :   CodeAssistantServiceImpl.java
 * Author    :   shadow guo
 * Create    :   2013-6-19 下午2:21:34
 *
 * Copyright 2008 by Tongfu Information Technology Co. Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Tongfu Information Technology Co. Ltd. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Tongfu Information Technology Co. Ltd.
 * 
 */
package com.tongfusoft.web.core.service.impl.codeassistant;

import java.sql.Connection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.yaml.snakeyaml.Yaml;

import com.tongfusoft.da.help.DBUtils;
import com.tongfusoft.exception.ServiceException;
import com.tongfusoft.utils.MapUtils;
import com.tongfusoft.web.core.service.codeassistant.ICodeAssistantService;
import com.tongfusoft.web.utils.CodeAssistTools;
import com.tongfusoft.web.utils.JDBCUtils;
import com.tongfusoft.web.utils.SqlParser;
import com.tongfusoft.web.utils.TableDefine;

public class CodeAssistantServiceImpl implements ICodeAssistantService {
	/**
	 * Logger for this class
	 */
	private static final Log logger = LogFactory
			.getLog(CodeAssistantServiceImpl.class);

	private SqlParser parser = new SqlParser();

	@Override
	public Map<String, Object> parserSQL(String sql) {
		try {
			parser.setSql(sql.toUpperCase());
			parser.parser();

			Map<String, Object> result = new HashMap<String, Object>();
			result.put("select",
					StringUtils.defaultIfEmpty(parser.getCols(), ""));
			result.put("from",
					StringUtils.defaultIfEmpty(parser.getTables(), ""));
			result.put("where",
					StringUtils.defaultIfEmpty(parser.getConditions(), ""));
			result.put("groupby",
					StringUtils.defaultIfEmpty(parser.getGroupCols(), ""));
			result.put("orderby",
					StringUtils.defaultIfEmpty(parser.getOrderCols(), ""));
			result.put("columns", parser.getColList());

			return result;
		} catch (Exception e) {
			throw new ServiceException("解析错误");
		}
	}

	@Override
	public String genListYaml(String jsonStr) {
		JSONObject jsonObj = JSONObject.fromObject(jsonStr);
		StringBuffer sb = new StringBuffer();

		sb.append("---").append(TableDefine.BR);
		sb.append("#").append(jsonObj.getString("listName")).append(TableDefine.BR);
		sb.append(jsonObj.getString("tagName")).append(": ").append(TableDefine.BR);
		sb.append(TableDefine.TAB).append("listName: ")
				.append(jsonObj.getString("listName")).append(TableDefine.BR);
		sb.append(TableDefine.TAB).append("titleDefs: ").append(TableDefine.BR);

		JSONArray titleDefs = jsonObj.getJSONArray("rowData");
		for (int i = 0; i < titleDefs.size(); i++) {
			JSONObject titleDef = titleDefs.getJSONObject(i);
			sb.append(TableDefine.TAB).append(TableDefine.TAB).append("- key: ")
					.append(titleDef.getString("columnName")).append(TableDefine.BR);
			sb.append(TableDefine.TAB).append(TableDefine.TAB).append("  title: ")
					.append(titleDef.getString("displayName")).append(TableDefine.BR);
			if (!titleDef.getBoolean("columnExport")) {
				sb.append(TableDefine.TAB).append(TableDefine.TAB).append("  isExport: false ")
						.append(TableDefine.BR);
			}
		}

		sb.append(TableDefine.TAB).append("select: | ").append(TableDefine.BR);
		sb.append(TableDefine.TAB).append(TableDefine.TAB).append(TableDefine.TAB)
				.append(jsonObj.getString("select")).append(TableDefine.BR);

		sb.append(TableDefine.TAB).append("from: | ").append(TableDefine.BR);
		sb.append(TableDefine.TAB).append(TableDefine.TAB).append(TableDefine.TAB)
				.append(jsonObj.getString("from")).append(TableDefine.BR);

		sb.append(TableDefine.TAB).append("where: | ").append(TableDefine.BR);
		sb.append(TableDefine.TAB).append(TableDefine.TAB).append(TableDefine.TAB)
				.append(jsonObj.getString("where")).append(TableDefine.BR);

		sb.append(TableDefine.TAB).append("groupby: | ").append(TableDefine.BR);
		sb.append(TableDefine.TAB).append(TableDefine.TAB).append(TableDefine.TAB)
				.append(jsonObj.getString("groupby")).append(TableDefine.BR);

		sb.append(TableDefine.TAB).append("orderby: | ").append(TableDefine.BR);
		sb.append(TableDefine.TAB).append(TableDefine.TAB).append(TableDefine.TAB)
				.append(jsonObj.getString("orderby")).append(TableDefine.BR);

		if (logger.isDebugEnabled()) {
			logger.debug(sb.toString());
		}

		return sb.toString();
	}

	@Override
	public String genJqGrid(String jsonStr) {
		try {
			JSONObject jsonObj = JSONObject.fromObject(jsonStr);

			String template = getJqGridTemplate();
			/*
			 * colNames colModel id caption
			 */
			JSONArray titleDefs = jsonObj.getJSONArray("rowData");

			String caption = jsonObj.getString("listName");
			String colNames = getColumnNames(titleDefs);
			String id = getPk(titleDefs);
			String colModel = columnModel(titleDefs);

			return String.format(template, colNames, colModel, id, caption);

		} catch (Exception e) {
			throw new ServiceException(e.getMessage());
		}
	}

	private String columnModel(JSONArray titleDefs) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < titleDefs.size(); i++) {
			JSONObject titleDef = titleDefs.getJSONObject(i);
			sb.append("{").append(TableDefine.BR);
			sb.append(TableDefine.TAB).append("name : '")
					.append(getWarpName(titleDef.getString("columnName")))
					.append("',").append(TableDefine.BR);
			sb.append(TableDefine.TAB).append("jsonmap : '")
					.append(titleDef.getString("columnName")).append("',")
					.append(TableDefine.BR);
			sb.append(TableDefine.TAB).append("index : '")
					.append(titleDef.getString("columnName")).append("',")
					.append(TableDefine.BR);

			if (titleDef.getBoolean("columnHid")) {
				sb.append(TableDefine.TAB).append("hidden: true,").append(TableDefine.BR);
			}

			if (!titleDef.getBoolean("columnEdit")) {
				sb.append(TableDefine.TAB).append("editable: false,").append(TableDefine.BR);
			} else {
				sb.append(TableDefine.TAB).append("editable: true,").append(TableDefine.BR);
			}

			if (titleDef.getString("columnType").equals("Date")) {
				sb.append(TableDefine.TAB).append("formatter : 'date',").append(TableDefine.BR);
				sb.append(TableDefine.TAB)
						.append("formatoptions : { newformat : 'Y-m-d'},")
						.append(TableDefine.BR);

				sb.append(TableDefine.TAB).append("editoptions: {").append(TableDefine.BR);
				sb.append(TableDefine.TAB).append("maxlengh: 10,").append(TableDefine.BR);
				sb.append(TableDefine.TAB).append("dataInit: function (element) { ")
						.append(TableDefine.BR);
				sb.append(TableDefine.TAB)
						.append("$(element).datepicker({ dateFormat: 'yy-mm-dd' } )}},")
						.append(TableDefine.BR);
				sb.append(TableDefine.TAB).append("editrules: { date: true},").append(TableDefine.BR);
			}

			if (titleDef.getBoolean("columnSearch")) {
				if (titleDef.getString("columnType").equals("VarChar")) {
					sb.append(TableDefine.TAB).append(
							"searchoptions : { sopt : [ \"eq\", \"cn\" ] },");
				} else if (titleDef.getString("columnType").equals("Date")) {
					sb.append(TableDefine.TAB)
							.append("searchoptions : { sopt : [ \"eg\", \"lt\",\"gt\" ] },");
				} else if (titleDef.getString("columnType").equals("Number")) {
					sb.append(TableDefine.TAB)
							.append("searchoptions : { sopt : [ \"eg\", \"lt\",\"gt\" ] },");
				}

				sb.append(TableDefine.TAB).append("search : true").append(TableDefine.BR);
			} else {
				sb.append(TableDefine.TAB).append("search : false").append(TableDefine.BR);
			}

			sb.append("}");

			if (i < (titleDefs.size() - 1)) {
				sb.append(",");
			}

		}

		return sb.toString();
	}

	public String getWarpName(String fieldName) {
		if (StringUtils.equals("LAST_UPD_DATE", fieldName.toUpperCase())) {
			return CodeAssistTools.lastUpdDate;
		} else if (StringUtils.equals("CREATED_DATE", fieldName.toUpperCase())) {
			return CodeAssistTools.createdDate;
		} else {
			String[] warpNames = StringUtils
					.split(fieldName.toLowerCase(), "_");
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < warpNames.length; i++) {
				if (i == 0) {
					sb.append(warpNames[i]);
				} else {
					sb.append(warpNames[i].substring(0, 1).toUpperCase()
							+ warpNames[i].substring(1));
				}

			}
			return sb.toString();
		}
	}

	private String getPk(JSONArray titleDefs) {
		for (int i = 0; i < titleDefs.size(); i++) {
			JSONObject titleDef = titleDefs.getJSONObject(i);
			if (titleDef.getBoolean("columnPK")) {
				return titleDef.getString("columnName");
			}
		}

		return "";
	}

	private String getColumnNames(JSONArray titleDefs) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < titleDefs.size(); i++) {
			JSONObject titleDef = titleDefs.getJSONObject(i);
			sb.append("\"").append(titleDef.getString("displayName"))
					.append("\"");

			if (i < (titleDefs.size() - 1)) {
				sb.append(",");
			}

			if (i % 4 == 0 && i != 0) {
				sb.append(TableDefine.BR);
			}
		}

		return sb.toString();
	}

	private String getJqGridTemplate() {
		try {
			Yaml yaml = new Yaml();

			for (Object config : yaml.loadAll(this.getClass()
					.getResourceAsStream("/bean.yaml"))) {
				Map<String, Object> properties = (Map<String, Object>) config;
				if (properties.containsKey("jqGrid")) {
					return (String) properties.get("jqGrid");
				}
			}

			return "";

		} catch (Exception e) {
			throw new ServiceException(e);
		}

	}
	
	private Map<String,Object> getDbInfo(String dbId){
		String dbSql = "select DB_ID,DB_DRIVER,DB_URL,DB_USERNAME,DB_USERPWD from t_dbinfo where status = '1' and db_id = #{dbId}";
		List<Map<String,Object>> db = DBUtils.executeSelectDynamic(dbSql, MapUtils.factory().put("dbId", dbId).create());
		if(db != null && db.size() >0 ){
			return db.get(0);
		}
		
		return null;
	}

	@Override
	public List<Map<String, String>> getAllTable(String dbId) {
		try{
			Map<String,Object> db = getDbInfo(dbId);
			
			if(db != null){
				Connection conn = JDBCUtils.getConn(db);
				List<Map<String, String>> result = JDBCUtils.getAllTable(conn, ((String)db.get("DB_USERNAME")).toUpperCase());
				//补充dbId
				for(Map<String, String> map : result){
					map.put("dbId", dbId);
				}
				
				return result;
			}
			
			return Collections.EMPTY_LIST;
		} catch (Exception e){
			throw new ServiceException(e);
			
		}
	}

	@Override
	public Map<String, String> genBeanCode(String dbId, String tableName) {
		try{
			Map<String,Object> db = getDbInfo(dbId);
			
			Map<String,String> result = new HashMap<String,String>();
			
			if(db != null){
				Connection conn = JDBCUtils.getConn(db);
				TableDefine tableDefine = JDBCUtils.getTableDefine(conn, ((String)db.get("DB_USERNAME")).toUpperCase(), tableName);
				tableDefine = JDBCUtils.setUnqieIndex(conn, tableDefine);
				
				//gen bean
				result.put("beanCode", tableDefine.getBean());
				//gen yaml
				result.put("yamlCode", tableDefine.getCUDSQL());
			}
			
			return result;
		} catch (Exception e){
			throw new ServiceException(e);
		}
	}

}
